package com.gxar.quick.ar.server.base.facade;

import cn.hutool.core.lang.Validator;
import com.alibaba.excel.EasyExcel;
import com.google.common.collect.Lists;
import com.gxar.common.entity.Result;
import com.gxar.common.entity.login.UserProfile;
import com.gxar.common.exception.APIRuntimeException;
import com.gxar.common.utils.*;
import com.gxar.quick.ar.server.base.async.exchange.event.AutoExchangeEvent;
import com.gxar.quick.ar.server.base.async.sms.dto.BatchSmsDTO;
import com.gxar.quick.ar.server.base.async.sms.event.AliBatchSmsEvent;
import com.gxar.quick.ar.server.base.async.user.listener.UserExchangeItemImportListener;
import com.gxar.quick.ar.server.base.common.constant.UserConstant;
import com.gxar.quick.ar.server.base.common.constant.WechatPayConstant;
import com.gxar.quick.ar.server.base.common.enums.*;
import com.gxar.quick.ar.server.base.common.enums.order.OrderMethodEnum;
import com.gxar.quick.ar.server.base.common.enums.order.OrderProductTypeEnum;
import com.gxar.quick.ar.server.base.common.enums.order.OrderPropertyEnum;
import com.gxar.quick.ar.server.base.common.enums.order.OrderStatusEnum;
import com.gxar.quick.ar.server.base.common.properties.ExchangeSendProperties;
import com.gxar.quick.ar.server.base.common.properties.UserProperties;
import com.gxar.quick.ar.server.base.common.utils.MapUtil;
import com.gxar.quick.ar.server.base.common.utils.TransferUtils;
import com.gxar.quick.ar.server.base.model.ResultCodeEnum;
import com.gxar.quick.ar.server.base.model.order.vo.request.OrderCreateRequest;
import com.gxar.quick.ar.server.base.model.pay.info.WechatPrepayAttachInfo;
import com.gxar.quick.ar.server.base.model.pay.vo.request.WechatPrepayRequest;
import com.gxar.quick.ar.server.base.model.pay.vo.response.WechatPrepayResponse;
import com.gxar.quick.ar.server.base.model.transaction.vo.request.CreateTransactionOrderRequest;
import com.gxar.quick.ar.server.base.model.user.vo.ExchangeCodeVO;
import com.gxar.quick.ar.server.base.model.user.vo.UserExchangeItemImportVO;
import com.gxar.quick.ar.server.base.model.user.vo.request.ComboBuyRequest;
import com.gxar.quick.ar.server.base.model.user.vo.request.CreateUserRequest;
import com.gxar.quick.ar.server.base.model.user.vo.request.UpdateUserRequest;
import com.gxar.quick.ar.server.base.model.user.vo.response.*;
import com.gxar.quick.ar.server.base.reference.UserReference;
import com.gxar.quick.ar.server.base.sdk.WechatPaySDK;
import com.gxar.quick.ar.server.db.model.*;
import com.gxar.quick.ar.server.db.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author nice
 * @version 1.0
 * @created 2023/11/15.
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class UserFacade {

    private final ExchangeSendProperties exchangeSendProperties;

    private final UserProperties userProperties;

    private final ComboService comboService;

    private final WechatPaySDK wechatPaySDK;

    private final OrderService orderService;

    private final TransactionService transactionService;

    private final UserService userService;

    private final ExchangeItemService exchangeItemService;

    private final UserReference userReference;

    private final ApplicationEventPublisher applicationEventPublisher;

    private final ExchangeItemFacade exchangeItemFacade;

    /**
     * 套餐会员套餐
     *
     * @param userProfile     用户信息
     * @param comboBuyRequest 套餐购买请求
     * @return
     */
    @Transactional(rollbackFor = Throwable.class)
    public Result<ComboBuyResponse> comboBuy(UserProfile userProfile, ComboBuyRequest comboBuyRequest) {
        ComboBuyResponse result = new ComboBuyResponse();
        Long comboId = comboBuyRequest.getComboId();
        String openId = TransferUtils.getOpenId(WechatPayConstant.APP_ID, userProfile);
        result.setComboId(comboId);
        //step 0 : 获取套餐信息
        ComboEntity comboEntity = comboService.getById(comboId);
        AssertUtils.notNull(comboEntity, ResultCodeEnum.COMBO_NOT_EXIST);
        //step 1 : 验证前端传参
        Integer method = comboBuyRequest.getMethod();
        UserInfoResponse userInfoResponse = userService.userInfo(userProfile);
        AssertUtils.notNull(userInfoResponse, ResultCodeEnum.USER_NOT_EXIST);
        if (OrderMethodEnum.BUY.getCode().equals(method)) {
            AssertUtils.isNull(userInfoResponse.getComboStartTime(), ResultCodeEnum.ORDER_METHOD_NOT_MATCH);
        }
        if (OrderMethodEnum.RENEWAL.getCode().equals(method)) {
            AssertUtils.notNull(userInfoResponse.getComboStartTime(), ResultCodeEnum.ORDER_RENEW_NOT_MATCH);
        }
        //step 2 : 创建订单
        OrderCreateRequest orderCreateRequest = new OrderCreateRequest();
        orderCreateRequest.setPrice(comboEntity.getPrice());
        orderCreateRequest.setOriPrice(comboEntity.getOriPrice());
        orderCreateRequest.setMethod(method);
        OrderEntity order = orderService.create(userProfile, orderCreateRequest);
        result.setOrderId(String.valueOf(order.getId()));
        //step 3 : 创建订单支付信息
        CreateTransactionOrderRequest createTransactionOrderRequest = getCreateTransactionOrderRequest(order);
        TransactionOrderEntity transactionOrder = transactionService.createTransactionOrder(userProfile,
                createTransactionOrderRequest);
        Long transactionOrderId = transactionOrder.getId();
        //step 4 : 创建订单产品
        OrderProductEntity orderProductEntity = getOrderProductEntity(order.getId(), comboId, comboEntity,
                userInfoResponse);
        orderService.createOrderProduct(userProfile, orderProductEntity);
        //step 5 : 调用微信预支付
        WechatPrepayRequest wechatPrepayRequest = getWechatPrepayRequest(userProfile, openId, comboEntity,
                transactionOrderId, comboId, orderProductEntity, order, transactionOrder);
        WechatPrepayResponse prepay = wechatPaySDK.prepay(WechatPayConstant.APP_ID, wechatPrepayRequest);
        //预支付成功
        if (prepay != null && StringUtils.isNotBlank(prepay.getPrepayId())) {
            //step 6 : 更新订单状态为支付中
            orderService.updateOrderStatus(order, OrderStatusEnum.PAYING);
            //step 7 : 记录预支付信息
            log.info("paySign: {}, prepayId: {}, nonceStr: {}, timeStamp: {}", prepay.getPaySign(),
                    prepay.getPrepayId(), prepay.getNonceStr(), prepay.getTimestamp());
            result.setPaySign(prepay.getPaySign());
            result.setPrepayId(prepay.getPrepayId());
            result.setSignType("RSA");
            result.setNonceStr(prepay.getNonceStr());
            result.setTimeStamp(String.valueOf(prepay.getTimestamp()));
        }
        return Result.success(result);
    }

    @NotNull
    private static WechatPrepayRequest getWechatPrepayRequest(UserProfile userProfile, String openId,
                                                              ComboEntity comboEntity, Long transactionOrderId, Long comboId, OrderProductEntity orderProductEntity,
                                                              OrderEntity order, TransactionOrderEntity transactionOrder) {
        WechatPrepayRequest wechatPrepayRequest = new WechatPrepayRequest();
        wechatPrepayRequest.setOpenId(openId);
        wechatPrepayRequest.setAmount(comboEntity.getPrice().multiply(BigDecimal.valueOf(100)).intValue());
        WechatPrepayAttachInfo attachInfo = new WechatPrepayAttachInfo();
        attachInfo.setTransactionOrderId(transactionOrderId);
        attachInfo.setComboId(comboId);
        attachInfo.setUserId(userProfile.getId());
        attachInfo.setStartTime(orderProductEntity.getStartTime());
        attachInfo.setEndTime(orderProductEntity.getEndTime());
        attachInfo.setType(orderProductEntity.getType());
        wechatPrepayRequest.setAttach(JacksonUtils.toJsonString(attachInfo));
        wechatPrepayRequest.setOutTradeNo(String.valueOf(order.getId()));
        wechatPrepayRequest.setDescription(comboEntity.getName());
        wechatPrepayRequest.setTimeExpire(transactionOrder.getTimeExpire());
        return wechatPrepayRequest;
    }

    @NotNull
    private static CreateTransactionOrderRequest getCreateTransactionOrderRequest(OrderEntity order) {
        CreateTransactionOrderRequest createTransactionOrderRequest = new CreateTransactionOrderRequest();
        createTransactionOrderRequest.setType(TransactionTypeEnum.PAY.getCode());
        createTransactionOrderRequest.setSource(TransactionSourceEnum.ORDER.getCode());
        createTransactionOrderRequest.setPlatform(TransactionPlatformEnum.WECHAT.getCode());
        createTransactionOrderRequest.setOrderId(order.getId());
        createTransactionOrderRequest.setPrice(order.getActualPrice());
        return createTransactionOrderRequest;
    }

    @NotNull
    private static OrderProductEntity getOrderProductEntity(Long orderId, Long comboId, ComboEntity comboEntity,
                                                            UserInfoResponse userInfoResponse) {
        OrderProductEntity orderProductEntity = new OrderProductEntity();
        orderProductEntity.setOrderId(Long.valueOf(orderId));
        orderProductEntity.setProductId(comboId);
        orderProductEntity.setType(OrderProductTypeEnum.MEMBER.getCode());
        orderProductEntity.setProperty(OrderPropertyEnum.DATE.getCode());
        orderProductEntity.setPropValue(comboEntity.getItemValue());
        orderProductEntity.setPropValueUnit(comboEntity.getItemValueUnit());
        orderProductEntity.setConfigInfo(comboEntity.getConfig());
        Integer item = comboEntity.getItem();
        if (ComboItemEnum.DATE.getCode().equals(item)) {
            Date comboEndTime = userInfoResponse.getComboEndTime();
            orderProductEntity.setStartTime(
                    comboEndTime == null ? new Date() : DateTimeUtils.addSeconds(comboEndTime, 1));
            Integer itemValue = comboEntity.getItemValue();
            String itemValueUnit = comboEntity.getItemValueUnit();
            if (ComboItemValueUnitEnum.YEAR.getName().equals(itemValueUnit)) {
                orderProductEntity.setEndTime(DateTimeUtils.getDayEndTime(
                        DateTimeUtils.addYears(orderProductEntity.getStartTime(), itemValue)));
            } else if (ComboItemValueUnitEnum.MONTH.getName().equals(itemValueUnit)) {
                orderProductEntity.setEndTime(DateTimeUtils.getDayEndTime(
                        DateTimeUtils.addMonths(orderProductEntity.getStartTime(), itemValue)));
            }
        }
        return orderProductEntity;
    }

    /**
     * 创建用户
     *
     * @param userProfile 用户信息
     * @param request     请求
     * @return 响应
     */
    @Transactional(rollbackFor = Throwable.class)
    public CreateUserResponse createUser(UserProfile userProfile, CreateUserRequest request) {
        if (request.getCodes().size() > 10) {
            throw new APIRuntimeException(ResultCodeEnum.USER_EXCHANGE_ADD_LIMIT);
        }
        String phone = request.getPhone();
        // 1、用户系统查询手机号是否存在.如果不存在则创建用户，并返回用户信息
        UserProfile checkUser = userReference.findUserByMobileWithAuthorize("", "", phone, UserConstant.USER_AUTO_REGISTER);
        if (Objects.isNull(checkUser) || StringUtils.isBlank(checkUser.getMobile())) {
            throw new APIRuntimeException(ResultCodeEnum.USER_CHECK_BY_MOBILE_ERROR);
        }

        // 2、根据用户系统返回的userid查询手机号是否存在
        Long userId = checkUser.getId();

        UserInfoEntity userInfoEntity = userService.findByUserId(userId);
        if (Objects.nonNull(userInfoEntity)) {
            throw new APIRuntimeException(ResultCodeEnum.USER_EXISTS);
        }
        // 3、保存用户信息
        userService.authorization(checkUser);
        CreateUserResponse response = new CreateUserResponse();
        response.setUserId(userId);
        if (CollectionUtils.isNotEmpty(request.getCodes())) {
            // 4、保存兑换品信息
            List<String> codes = request.getCodes().stream().map(ExchangeCodeVO::getCode).distinct().collect(Collectors.toList());
            List<ExchangeItemEntity> itemInCodeList = exchangeItemService.findItemInCodeList(codes);
            List<String> saveCodes = exchangeItemService.saveExchangeItemUser(userProfile, userId, phone, request.getCodes(), itemInCodeList);
            exchangeItemService.saveExchangeItemRecord(userProfile, userId, request.getCodes());
            for (ExchangeItemEntity exchangeItemEntity : itemInCodeList) {
                // 如果不是手动领取，其余领取方式都需要自动领取
                if (ExchangeMethodEnum.AUTO.getCode().equals(exchangeItemEntity.getMethod())) {
                    exchangeItemFacade.exchange(checkUser, exchangeItemEntity.getCode());
                }
            }
            response.setCodes(saveCodes);
            // 取消短信发送
//            List<BatchSmsDTO> batchSmsList = new ArrayList<>(1);
//            List<String> signList = Collections.singletonList(exchangeSendProperties.getSign());
//            BatchSmsDTO batchSms = new BatchSmsDTO();
//            batchSms.setPhone(phone);
//            batchSms.setParam(Collections.singletonList(StringUtils.join(saveCodes, "、")));
//            batchSmsList.add(batchSms);
//            // 发送短信
//            if (CollectionUtils.isNotEmpty(batchSmsList)) {
//                applicationEventPublisher.publishEvent(new AliBatchSmsEvent(this, batchSmsList, signList, SmsBusinessCodeEnum.EXCHANGE_SEND));
//            }
        }

        return response;
    }

    /**
     * 更新用户
     *
     * @param userProfile 用户信息
     * @param request     请求
     * @return 响应
     */
    @Transactional(rollbackFor = Throwable.class)
    public UpdateUserResponse updateUser(UserProfile userProfile, UpdateUserRequest request) {
        String phone = request.getPhone();
        //1.dubbo调用查询用户是否存在,如果不存在抛异常
        UserProfile checkUser = userReference.findUserByMobileWithAuthorize("", "", phone, UserConstant.USER_NO_AUTO_REGISTER);
        if (Objects.isNull(checkUser) || StringUtils.isBlank(checkUser.getMobile())) {
            throw new APIRuntimeException(ResultCodeEnum.USER_NOT_EXIST);
        }

        Long userId = checkUser.getId();
        UserInfoEntity userInfoEntity = userService.findByUserId(userId);
        if (Objects.isNull(userInfoEntity)) {
            userService.authorization(checkUser);
        }

        List<ExchangeCodeVO> exchangeCodeList = request.getCodes().stream().filter(e -> e.getNum() > 0).collect(Collectors.toList());
        UpdateUserResponse response = new UpdateUserResponse();
        response.setUserId(userId);
        if (CollectionUtils.isNotEmpty(exchangeCodeList)) {
            // 保存兑换品信息
            List<String> codes = request.getCodes().stream().map(ExchangeCodeVO::getCode).distinct().collect(Collectors.toList());
            List<ExchangeItemEntity> itemInCodeList = exchangeItemService.findItemInCodeList(codes);
            List<String> saveCodes = exchangeItemService.saveExchangeItemUser(userProfile, userId, phone, exchangeCodeList, itemInCodeList);
            exchangeItemService.saveExchangeItemRecord(userProfile, userId, exchangeCodeList);
            for (ExchangeItemEntity exchangeItemEntity : itemInCodeList) {
                // 如果不是手动领取，其余领取方式都需要自动领取
                if (ExchangeMethodEnum.AUTO.getCode().equals(exchangeItemEntity.getMethod())) {
                    exchangeItemFacade.exchange(checkUser, exchangeItemEntity.getCode());
                }
            }
            response.setCodes(saveCodes);

//            List<BatchSmsDTO> batchSmsList = new ArrayList<>(1);
//            List<String> signList = Collections.singletonList(exchangeSendProperties.getSign());
//            BatchSmsDTO batchSms = new BatchSmsDTO();
//            batchSms.setPhone(phone);
//            batchSms.setParam(Collections.singletonList(StringUtils.join(saveCodes, "、")));
//            batchSmsList.add(batchSms);
//            // 发送短信
//            if (CollectionUtils.isNotEmpty(batchSmsList)) {
//                applicationEventPublisher.publishEvent(new AliBatchSmsEvent(this, batchSmsList, signList, SmsBusinessCodeEnum.EXCHANGE_SEND));
//            }
        }
        return response;
    }

    /**
     * 导入用户兑换品
     *
     * @param userProfile 用户信息
     * @param file        文件
     * @return 响应
     * @throws IOException 异常
     */
    @Transactional(rollbackFor = Throwable.class)
    public UserExchangeItemImportResponse importUserExchangeItem(UserProfile userProfile, MultipartFile file) throws IOException {
        log.info("开始导入。。。");
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("解析文件");
        UserExchangeItemImportResponse response = new UserExchangeItemImportResponse();
        UserExchangeItemImportListener<UserExchangeItemImportVO> hmdImportListener = new UserExchangeItemImportListener<>();
        EasyExcel.read(file.getInputStream(), UserExchangeItemImportVO.class, hmdImportListener)
                .sheet()
                .doRead();

        // 字段解析错误
        StringBuilder totalErrorMessage = hmdImportListener.getTotalErrorMessage();
        String failReason = totalErrorMessage.toString();
        if (org.apache.commons.lang3.StringUtils.isNotBlank(failReason)) {
            // 状态改成处理失败
            Integer failedCount = hmdImportListener.getFailedCount();
            totalErrorMessage.insert(0, "失败条数总计：" + failedCount + "条，以下为部分失败内容，未展示内容请按照下方的失败内容自行排查；");
            String totalErrorStr = totalErrorMessage.toString();
            String totalError = totalErrorStr.length() > 1000 ? totalErrorStr.substring(0, 1000) : totalErrorStr;
            response.setFailReason(totalError);
            throw new APIRuntimeException(ResultCodeEnum.EXCEL_ERROR, totalError);
        }

        //成功导入的广告账号
        List<UserExchangeItemImportVO> successList = hmdImportListener.getSuccessList();
        stopWatch.stop();
        if (CollectionUtils.isEmpty(successList)) {
            response.setFailReason("表格数据为空");
            throw new APIRuntimeException(ResultCodeEnum.EXCEL_ERROR, "表格数据为空");
        }
        log.info("解析完成");
        stopWatch.start("手机号校验");
        // 不允许重复校验
//        Set<UserExchangeItemImportVO> successSet = new HashSet<>(successList);
//        if (successList.size() != successSet.size()) {
//            response.setFailReason("表格中存在重复的手机号和兑换品ID请检查后重试");
//            throw new APIRuntimeException(ResultCodeEnum.EXCEL_ERROR, "表格中存在重复的手机号和兑换品ID请检查后重试");
//        }
        // 一次导入最多5000条
        if (successList.size() > userProperties.getImportLimit()) {
            response.setFailReason("导入条数超过最大限制5000条");
            throw new APIRuntimeException(ResultCodeEnum.EXCEL_ERROR, "导入条数超过最大限制5000条");
        }
        // 限制每个用户一次最多导入10个
        Map<String, Long> phoneCodeNumber = successList.stream().collect(Collectors.groupingBy(UserExchangeItemImportVO::getPhone, Collectors.counting()));
        boolean codeLimit = phoneCodeNumber.entrySet().stream().anyMatch(e -> e.getValue() > 10L);
        if (codeLimit) {
            throw new APIRuntimeException(ResultCodeEnum.EXCEL_ERROR, "单次导入1个手机号最多导入10个兑换码");
        }
        List<String> phoneList = successList.stream().map(UserExchangeItemImportVO::getPhone).distinct().collect(Collectors.toList());
        // 校验手机号是否正确
        for (String phone : phoneList) {
            boolean mobile = Validator.isMobile(phone);
            if (!mobile) {
                response.setFailReason("手机号[" + phone + "]不正确");
                throw new APIRuntimeException(ResultCodeEnum.EXCEL_ERROR, "手机号[" + phone + "]不正确");
            }
        }
        stopWatch.stop();
        List<String> codeList = successList.stream().map(UserExchangeItemImportVO::getCode).distinct().collect(Collectors.toList());
        stopWatch.start("兑换码校验");
        // 校验兑换码是否正确
        List<List<String>> codePartition = Lists.partition(codeList, 1000);
        List<ExchangeItemEntity> exchangeItemEntityList = new ArrayList<>();
        for (List<String> codes : codePartition) {
            List<ExchangeItemEntity> exchangeItemEntities = exchangeItemService.findItemInCodeList(codes);
            if (CollectionUtils.isEmpty(exchangeItemEntities) || codes.size() != exchangeItemEntities.size()) {
                List<String> sysExchangeItemCodeList = Optional.ofNullable(exchangeItemEntities).orElse(Collections.emptyList()).stream().map(ExchangeItemEntity::getCode).collect(Collectors.toList());
                List<String> collect = codes.stream().filter(e -> !sysExchangeItemCodeList.contains(e)).collect(Collectors.toList());
                response.setFailReason("存在无效的兑换码:[" + StringUtils.join(collect, ",") + "]，请确认后再导入");
                throw new APIRuntimeException(ResultCodeEnum.EXCEL_ERROR, "存在无效的兑换码:[" + StringUtils.join(collect, ",") + "]，请确认后再导入");
            }
            exchangeItemEntityList.addAll(exchangeItemEntities);
        }
        Map<String, ExchangeItemEntity> exchangeItemEntityMap = exchangeItemEntityList.stream().collect(Collectors.toMap(ExchangeItemEntity::getCode, t -> t, (t1, t2) -> t1));
        stopWatch.stop();
        // 分批查询用户系统用户，不存在则创建
        List<List<String>> phonePartition = Lists.partition(phoneList, 1000);
        Map<String, UserProfile> userMap = new HashMap<>();
        stopWatch.start("分批创建用户");
        ComboEntity comboEntity = comboService.findByGrade(ComboGradeEnum.ORDINARY.getCode());
        for (List<String> phones : phonePartition) {
            List<UserProfile> userProfileList;
            try {
                userProfileList = userReference.batchUserByMobileWithAuthorize(null, null, phones, UserConstant.USER_AUTO_REGISTER);
                if (CollectionUtils.isEmpty(userProfileList)) {
                    throw new APIRuntimeException(ResultCodeEnum.EXCEL_ERROR, "手机号：[" + StringUtils.join(phones, ",") + "]，创建用户失败");
                }
            } catch (RuntimeException e) {
                throw new APIRuntimeException(ResultCodeEnum.EXCEL_ERROR, "手机号创建用户失败：[" + e.getMessage() + "]");
            }
            userService.authorizationByList(userProfile, userProfileList.stream().map(UserProfile::getId).collect(Collectors.toList()), comboEntity);
            for (UserProfile usrProfile : userProfileList) {
                //将用户信息批量校验是否在userInfo中  如果不存在则创建
                userMap.put(usrProfile.getMobile(), usrProfile);
            }
        }
        stopWatch.stop();
        int success = 0;
        String existsExchangeItemFailMsg = "";
        stopWatch.start("创建用户兑换品");
        Map<String, List<UserExchangeItemImportVO>> successMap = successList.stream().collect(Collectors.groupingBy(UserExchangeItemImportVO::getPhone));
        List<Map<String, List<UserExchangeItemImportVO>>> mapList = MapUtil.splitByChunkSize(successMap, 2);
        for (Map<String, List<UserExchangeItemImportVO>> phoneMap : mapList) {
            List<BatchSmsDTO> batchSmsList = new ArrayList<>();
            List<String> signList = new ArrayList<>();
            for (Map.Entry<String, List<UserExchangeItemImportVO>> successEntrySet : phoneMap.entrySet()) {
                String phone = successEntrySet.getKey();
                List<UserExchangeItemImportVO> successEntrySetValue = successEntrySet.getValue();
                List<String> entrySetCodeList = successEntrySetValue.stream().map(UserExchangeItemImportVO::getCode).collect(Collectors.toList());
                List<ExchangeItemUserEntity> saveList = new ArrayList<>();
                List<ExchangeItemSendRecordEntity> recordSaveList = new ArrayList<>();
                List<String> smsCode = new ArrayList<>();
                List<String> autoCode = new ArrayList<>();
                Long userId = userMap.get(phone).getId();
                for (String code : entrySetCodeList) {

                    ExchangeItemEntity exchangeItem = exchangeItemEntityMap.get(code);
                    // 判断是自动还是手动领取
                    if (ExchangeMethodEnum.AUTO.getCode().equals(exchangeItem.getMethod())) {
                        autoCode.add(code);
                    } else if (ExchangeMethodEnum.MANUAL.getCode().equals(exchangeItem.getMethod())) {
                        smsCode.add(code);
                    }

                    long userItemId = Long.parseLong(SnowFlakeUtils.getInstance().nextId());
                    ExchangeItemUserEntity exchangeItemUserEntity = exchangeItemService.buildExchangeItem(userProfile, userItemId, userId, phone, exchangeItem, null);
                    saveList.add(exchangeItemUserEntity);
                    ExchangeItemSendRecordEntity entity = exchangeItemService.buildExchangeItemSendRecordEntity(userProfile, userId, code);
                    recordSaveList.add(entity);
                }
                if (CollectionUtils.isNotEmpty(saveList)) {
                    Integer saved = exchangeItemService.saveExchangeItemUser(saveList);
                    success += saved;
                }
                if (CollectionUtils.isNotEmpty(recordSaveList)) {
                    exchangeItemService.saveExchangeItemRecord(recordSaveList);
                }
                if (CollectionUtils.isNotEmpty(smsCode)) {
                    BatchSmsDTO batchSms = new BatchSmsDTO();
                    batchSms.setPhone(phone);
                    batchSms.setParam(Collections.singletonList(StringUtils.join(smsCode, "、")));
                    batchSmsList.add(batchSms);
                    signList.add(exchangeSendProperties.getSign());
                }
                if (CollectionUtils.isNotEmpty(autoCode)) {
                    // 异步处理
                    UserProfile checkUser = new UserProfile();
                    checkUser.setId(userId);
                    checkUser.setMobile(phone);
                    for (String code : autoCode) {
                        applicationEventPublisher.publishEvent(new AutoExchangeEvent(this, checkUser, code));
                    }
                }
            }
            // 发送短信
            if (CollectionUtils.isNotEmpty(batchSmsList)) {
                applicationEventPublisher.publishEvent(new AliBatchSmsEvent(this, batchSmsList, signList, SmsBusinessCodeEnum.EXCHANGE_SEND));
            }
        }
        stopWatch.stop();
        String prettyPrint = stopWatch.prettyPrint();
        log.info("方法耗时：{}", prettyPrint);
        response.setFailReason(existsExchangeItemFailMsg);
        response.setSuccessNumber(success);
        return response;
    }
}
